package com.qding.park.manager.rest.conf;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.util.ClassUtils;

import com.alibaba.druid.pool.DruidDataSource;

@Service
@Scope("singleton")
@MapperScan(basePackages = {"com.qding.park.manager.adapter.factory.mapper",
                            "com.qding.park.manager.service.core.mapper",
                            "com.qding.park.manager.rest.mapper",
                            "com.qding.park.manager.cache.mapper" })
public class MybatisConfigBean {

    private static final Logger logger = LoggerFactory.getLogger(MybatisConfigBean.class);

    @Bean(name = "dataSource")
    public DataSource dataSource() {
        // // logger.info("druidDataSourceConfig=" + jdbcDatasourceConfig);
        Map<String, Object> datasurceConfMap = DisconfDataGetter
                .getByFile(DisconfDataGetter.jdbc_datasource_properties);
        logger.info("datasurceConfMap config ==> " + " datasurceConfMap:{}", datasurceConfMap);

        String driverClassName = String.valueOf(datasurceConfMap.get("driverClassName"));
        String username = String.valueOf(datasurceConfMap.get("username"));
        String password = String.valueOf(datasurceConfMap.get("password"));
        String url = String.valueOf(datasurceConfMap.get("url"));
        int maxActive = (int) datasurceConfMap.get("maxActive");
        String validationQuery = String.valueOf(datasurceConfMap.get("validationQuery"));
        boolean testOnBorrow = (boolean) datasurceConfMap.get("testOnBorrow");
        boolean testOnReturn = (boolean) datasurceConfMap.get("testOnReturn");
        boolean testWhileIdle = (boolean) datasurceConfMap.get("testWhileIdle");
        int timeBetweenEvictionRunsMillis = (int) datasurceConfMap.get("timeBetweenEvictionRunsMillis");
        int minEictableIdleTimeMillis = (int) datasurceConfMap.get("minEictableIdleTimeMillis");
        boolean poolPreparedStatements = (boolean) datasurceConfMap.get("poolPreparedStatements");
        int maxOpenPreparedStatements = (int) datasurceConfMap.get("maxOpenPreparedStatements");
        String filters = String.valueOf(datasurceConfMap.get("filters"));
        // // 加载配置文件属性
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driverClassName);
        ds.setUsername(username);
        ds.setPassword(password);
        ds.setUrl(url);
        ds.setMaxActive(maxActive);
        ds.setValidationQuery(validationQuery);
        ds.setTestOnBorrow(testOnBorrow);
        ds.setTestOnReturn(testOnReturn);
        ds.setTestWhileIdle(testWhileIdle);
        ds.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        ds.setMinEvictableIdleTimeMillis(minEictableIdleTimeMillis);
        ds.setPoolPreparedStatements(poolPreparedStatements);
        ds.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
        try {
            ds.setFilters(filters);
        } catch (SQLException e) {
            logger.error(e.getMessage(), e);
        }
        return ds;
    }

    @Bean(name = "sqlSessionFactory")
    @Lazy(true)
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        logger.debug("--> sqlSessionFactory");

        final SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        sqlSessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        sqlSessionFactory.setFailFast(true);
        sqlSessionFactory.setMapperLocations(getResource("mapper", "**/*.xml"));
        sqlSessionFactory.setTypeAliasesPackage("com.qding.park.manager.adapter.factory.mapper;com.qding.park.manager.service.core.mapper;com.qding.park.manager.cache.mapper");
        return sqlSessionFactory.getObject();
    }//com.qding.park.manager.service.statis.mapper

//    @Bean(name = "mapperScannerConfigurer")
//    @Lazy(true)
//    public MapperScannerConfigurer  getMapperScannerConfigurer(){
//        logger.debug("--> MapperScannerConfigurer");
//        MapperScannerConfigurer  mapperScannerConfigurer=new MapperScannerConfigurer();
//        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
//        mapperScannerConfigurer.setBasePackage("com.qding.park.manager.adapter.factory.mapper");
//        return mapperScannerConfigurer;
//    }
    
    //
    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager(DataSource dataSource) {
        logger.debug("> transactionManager");
        return new DataSourceTransactionManager(dataSource);
    }

    //
    public Resource[] getResource(String basePackage, String pattern) throws IOException {
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils
                .convertClassNameToResourcePath(new StandardEnvironment().resolveRequiredPlaceholders(basePackage))
                + "/" + pattern;
        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(packageSearchPath);
        return resources;
    }
}
